import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer, AsyncWebsocketConsumer
import datetime


class ChatConsumer(AsyncWebsocketConsumer):
    """
    异步模式，效率高一丢丢
    不涉及ORM操作使用异步会效率更高
    """

    # websocket建立连接时执行方法
    async def connect(self):
        print("scope:", self.scope)
        # 从url里获取聊天室名字，为每个房间建立一个频道组
        self.room_id = self.scope['url_route']['kwargs']['room_id']  # 获取传输的房间Id
        self.room_group_name = 'chat_%s' % self.room_id  # 添加分组名以chat_开头

        # 将当前频道加入频道组
        await self.channel_layer.group_add(
            self.room_group_name,  # 房间号标识 用于分组
            self.channel_name  # 个人标识
        )

        # 接受所有websocket请求
        await self.accept()

    # websocket断开时执行方法
    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # 从websocket接收到消息时执行函数
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # 发送消息到频道组，频道组调用chat_message方法
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message  # 把发送的信息放到event['message']字段里面
            }
        )

    # 从频道组接收到消息后执行方法
    async def chat_message(self, event):
        message = event['message']
        datetime_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        # 通过websocket发送消息到客户端
        await self.send(text_data=json.dumps({
            'message': f'{datetime_str}:{message}'
        }))


class ChatConsumerSync(WebsocketConsumer):
    """
    涉及ORM操作使用同步方式
    """

    # websocket建立连接时执行方法
    def connect(self):
        # print("scope:", self.scope)
        # 从url里获取聊天室名字，为每个房间建立一个频道组
        self.room_id = self.scope['url_route']['kwargs']['room_id']  # 获取传输的房间Id
        self.room_group_name = 'chat_%s' % self.room_id  # 添加分组名以chat_开头

        # 将当前频道加入频道组
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,  # 房间号标识 用于分组
            self.channel_name  # 个人标识
        )

        # 接受所有websocket请求
        self.accept()

    # websocket断开时执行方法
    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # 从websocket接收到消息时执行函数
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # 发送消息到频道组，频道组调用chat_message方法
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message  # 把发送的信息放到event['message']字段里面
            }
        )

    # 从频道组接收到消息后执行方法
    def chat_message(self, event):
        message = event['message']
        datetime_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        # 通过websocket发送消息到客户端
        self.send(text_data=json.dumps({
            'message': f'{datetime_str}:{message}'
        }))
